package com.yonyou.distribute.service;

import com.yonyou.distribute.zk.ZKDistributedLock_3;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.*;
import org.apache.curator.framework.recipes.shared.SharedCount;
import org.redisson.api.RLock;
import org.redisson.api.RSemaphore;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class CuratorService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private CuratorFramework curatorFramework;

    public void deduct() {
        InterProcessMutex mutex = new InterProcessMutex(curatorFramework, "/curator/locks");
        try{
            mutex.acquire();
            // 1、查询库存
            String stock = this.stringRedisTemplate.opsForValue().get("stock");
            // 2、判断库存是否充足
            if(!StringUtils.isEmpty(stock)){
                Integer st = Integer.valueOf(stock);
                if(st > 0){
                    //3、更新库存到数据库
                    this.stringRedisTemplate.opsForValue().set("stock", String.valueOf(--st));
                }
            }
            this.test(mutex);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                mutex.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 可重入
     * @param mutex
     * @throws Exception
     */
    public void test(InterProcessMutex mutex) throws Exception {
        mutex.acquire();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("测试可重入!");
        mutex.release();
    }

    public void testReadLock() {
        try {
            InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(curatorFramework, "/curator/rwLock");
            readWriteLock.readLock().acquire(5, TimeUnit.SECONDS);
//        readWriteLock.readLock().release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void testWriteLock() {
        try {
            InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(curatorFramework, "/curator/rwLock");
            readWriteLock.writeLock().acquire(5, TimeUnit.SECONDS);
//        readWriteLock.writeLock().release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void testSemaphore() {
        InterProcessSemaphoreV2 semaphoreV2 = new InterProcessSemaphoreV2(curatorFramework, "/curator/semaphore", 3);
        try {
            Lease acquire = semaphoreV2.acquire();
            this.stringRedisTemplate.opsForList().rightPush("log", "开始业务处理 " + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(5 + new Random().nextInt(5));
            this.stringRedisTemplate.opsForList().rightPush("log", "业务处理结束，释放资源 " + Thread.currentThread().getName());
            semaphoreV2.returnLease(acquire);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 共享计数器  多个服务器可以共享数据
    public void testShareCount() {
        try {
            SharedCount sharedCount = new SharedCount(curatorFramework, "/curator/shareCount", 100);
            sharedCount.start();
            int count = sharedCount.getCount();
            int random = new Random().nextInt(1000);
            sharedCount.setCount(random);
            System.out.println("共享计数器的初始值：" + count + " , 更新后：" + random);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
